extension :restart => :webobjects_wotaskd do
  
  set(:_hosts_and_ports) do
    site_configs = Hash.new { |h,k| h[k] = "" }
    run "cat #{fetch(:wotaskd_site_config_path, "/Library/WebObjects/Configuration/SiteConfig.xml")}" do |channel, stream, data|
      site_configs[channel] += data
    end    
    
    result = site_configs.map do |channel,site_config|
      doc = REXML::Document.new(site_config)
      REXML::XPath.match(doc, "//instanceArray/element/applicationName[. = '#{project_name}']/parent::*/.").map do |instance|
        [channel[:server].to_s, instance.elements["hostName"].text, Integer(instance.elements["port"].text)]
      end
    end.flatten(1)
    raise RuntimeError.new("didn't find any hosts/ports") if result.empty?
    
    logger.info "found hosts/ports for #{project_name}"
    result.each do |server,host, port|
      logger.info "#{server}=>#{host}:#{port}"
    end
    result
  end
  
  task :restart, :roles => :app do
    hosts_ports = fetch :_hosts_and_ports
    
    terminate_request =<<__EOF
<instanceRequest type="NSDictionary">
 <commandInstance type="NSDictionary">
  <command type="NSString">TERMINATE</command>
 </commandInstance>
</instanceRequest>
__EOF
    
    http_terminate_request  =<<__EOF
POST #{fetch(:webobjects_prefix, "/cgi-bin/WebObjects")}/#{project_name}.woa/womp/instanceRequest HTTP/1.0
cookie:
content-length: #{terminate_request.length}

#{terminate_request}
__EOF
    
    rb_port_writer = <<-__EOF
require "socket"
require "timeout"

puts "reading request from stdin..."
request = STDIN.read
port = ARGV[0]

response = nil
timeout(10) do
  TCPSocket.open("localhost", port) do |s|
    puts "socket opened, sending request..."
    s.write(request)
    puts "request sent, reading response..."
    response = s.read
    puts "response read, finishing..."
  end
end

STDOUT.write(response)
STDOUT.flush
__EOF
    rb_port_writer_tmp_path = "/tmp/_rb_port_writer.rb"
    rb_port_writer_request_tmp_path = "/tmp/_rb_port_writer_request"

    put rb_port_writer, rb_port_writer_tmp_path
    begin
      put http_terminate_request, rb_port_writer_request_tmp_path

      failed_restarts = []
      hosts_ports.each do |server, host, port|
        success_flag = false
        begin
          run "ruby '#{rb_port_writer_tmp_path}' #{port} < #{rb_port_writer_request_tmp_path} 2>&1", :hosts => server do |channel, stream, data|
            logger.debug data
            success_flag = true if data =~ /<success type="NSString">YES<\/success>/
          end
        rescue => e
          logger.important e.to_s
        end
        unless success_flag
          logger.important "can't restart instance on #{server} => #{host}:#{port}" 
          failed_restarts << [server, host, port]
        end
      end

      raise RuntimeError.new("restart failed on following hosts/ports: #{failed_restarts.map { |c,h,p| "#{c[:host]}=>#{h}:#{p}"}.join(", ")}") unless failed_restarts.empty?
    ensure
      run "rm -f '#{rb_port_writer_tmp_path}'"
      run "rm -f '#{rb_port_writer_request_tmp_path}'"
    end
  end
end

#compat_extension do
#  
#  namespace :wondercap do
#    desc "restarts all instances of the given application"
#    task :webobjects_wotaskd_restart, :roles => :app do
#      site_config_path = fetch(:site_config_path, nil)
#      webobjects_prefix = fetch(:prefix, nil)
#
#      strategy.project_name = fetch(:app_name)
#      strategy.use(:webobjects_wotaskd).for(:restart) {
#        set :site_config_path, site_config_path if site_config_path
#        set :webobjects_prefix, webobjects_prefix if webobjects_prefix
#      }
#
#      strategy.restart
#    end
#  end
#  
#end
